home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- MODULE: rgets.c
- PURPOSE: recio character delimited string and char input functions
- COPYRIGHT: (C) 1994 William Pierpoint
- COMPILER: Borland C Version 3.1
- OS: MSDOS Version 6.2
- VERSION: 2.00
- RELEASE: April 15, 1994
- *****************************************************************************/
-
- #include <ctype.h>
- #include <errno.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #include "recio.h"
-
- extern int _rstatus(REC *rp, int mode);
- extern void _rsetexitfn(REC *rp);
-
- /* private macros */
- #define RECBUFSIZ_MIN 2 /* min one character and new line */
- #define FLDBUFSIZ_MIN 1 /* min one character */
-
- #define RECBUFSIZE max(RECBUFSIZ, RECBUFSIZ_MIN)
- #define FLDBUFSIZE max(FLDBUFSIZ, FLDBUFSIZ_MIN)
-
- #define READ 0
-
- #define rcol(rp) ((rp)->r_colno)
- #define rflags(rp) ((rp)->r_flags)
- #define rfd(rp) ((rp)->r_fd)
- #define rfp(rp) ((rp)->r_fp)
- #define rreclen(rp) ((rp)->r_reclen)
- #define rrecsiz(rp) ((rp)->r_recsiz)
- #define rfldsiz(rp) ((rp)->r_fldsiz)
- #define rfldch(rp) ((rp)->r_fldch)
- #define rtxtch(rp) ((rp)->r_txtch)
-
- /****************************************************************************/
- static int /* return error number (0=no error) */
- _rsetfldsiz( /* set field buffer size */
- REC *rp, /* record pointer */
- size_t fldsiz) /* field buffer size */
- /****************************************************************************/
- {
- int errnum=0; /* error number */
- char *fldp; /* pointer to new field buffer */
-
- /* if no memory allocated to field buffer */
- if (!rflds(rp)) {
-
- /* determine minimum size of field buffer */
- fldsiz = max(fldsiz, FLDBUFSIZE);
-
- /* initially allocate memory for field buffer */
- do {
- fldp = (char *) calloc(fldsiz+1, sizeof(char));
- if (!fldp) {
- errnum = rseterr(rp, R_ENOMEM);
- if (errnum) goto done;
- }
- } while (!fldp);
- rflds(rp) = fldp;
- rfldsiz(rp) = fldsiz;
- _rsetexitfn(rp);
-
- /* if field buffer needs to be larger */
- } else if (fldsiz > rfldsiz(rp)) {
-
- /* reallocate memory for field buffer */
- do {
- fldp = (char *) realloc(rflds(rp), fldsiz+1);
- if (!fldp) {
- errnum = rseterr(rp, R_ENOMEM);
- if (errnum) goto done;
- }
- } while (!fldp);
- rflds(rp) = fldp;
- rfldsiz(rp) = fldsiz;
- }
-
- done:
- return (errnum);
- }
-
- /****************************************************************************/
- static int /* return error number (0=no error) */
- _rsetrecsiz( /* set record buffer size */
- REC *rp, /* record pointer */
- size_t recsiz) /* record buffer size */
- /****************************************************************************/
- {
- int errnum=0; /* error number */
- char *recp; /* pointer to new record buffer */
-
- /* if no memory allocated to field buffer */
- if (!rrecs(rp)) {
-
- /* determine minimum size of record buffer */
- recsiz = max(recsiz, RECBUFSIZE);
-
- /* initially allocate memory for record buffer */
- do {
- recp = (char *) calloc(recsiz+1, sizeof(char));
- if (!recp) {
- errnum = rseterr(rp, R_ENOMEM);
- if (errnum) goto done;
- }
- } while (!recp);
- rrecs(rp) = recp;
- rrecsiz(rp) = recsiz;
- _rsetexitfn(rp);
-
- /* if record buffer needs to be larger */
- } else if (recsiz > rrecsiz(rp)) {
-
- /* reallocate memory for record buffer */
- do {
- recp = (char *) realloc(rrecs(rp), recsiz+1);
- if (!recp) {
- errnum = rseterr(rp, R_ENOMEM);
- if (errnum) goto done;
- }
- } while (!recp);
- rrecs(rp) = recp;
- rrecsiz(rp) = recsiz;
- }
-
- done:
- return (errnum);
- }
-
- /****************************************************************************/
- static int /* return !0 on match */
- isfldch( /* is character the field separator character? */
- REC *rp, /* record pointer */
- int ch) /* character to test */
- /****************************************************************************/
- {
- int ismatch=0; /* return 0 if no match */
-
- if (isascii(ch)) {
- if (rfldch(rp) == ' ') {
- ismatch = isspace(ch);
- } else {
- ismatch = (!(ch - rfldch(rp)));
- }
- }
- return (ismatch);
- }
-
- /****************************************************************************/
- static int /* return !0 on match */
- istxtch( /* is character the text delimiter character? */
- REC *rp, /* record pointer */
- int ch) /* character to test */
- /****************************************************************************/
- {
- int ismatch=0; /* return 0 if no match */
-
- if (isascii(ch)) {
- if (rtxtch(rp) == ' ') {
- ismatch = isspace(ch);
- } else {
- ismatch = (!(ch - rtxtch(rp)));
- }
- }
- return (ismatch);
- }
-
- /****************************************************************************/
- static size_t /* return length of field */
- _rfldlen( /* get length of field */
- REC *rp) /* record pointer */
- /****************************************************************************/
- {
- size_t len=0; /* length of field (0=missing field)*/
- size_t col; /* column location */
- int ch; /* character at column location */
- int qstate=0; /* quoted string state (0=off; 1=on) */
-
- /* get column location for first non-whitespace character in field */
- for (col=rcol(rp); col < rreclen(rp); col++) {
- if (!isspace(rrecs(rp)[col])) break;
- }
-
- /* find field separator at end of field */
- if (istxtch(rp, ' ')) {
- for (; col < rreclen(rp); col++) {
- ch = rrecs(rp)[col];
- if (isfldch(rp, ch)) break;
- }
- } else {
- for (; col < rreclen(rp); col++) {
- ch = rrecs(rp)[col];
- /* don't search for fldch between txtch's */
- if (istxtch(rp, ch)) qstate = !qstate;
- if (!qstate && isfldch(rp, ch)) break;
- }
- }
-
- /* get length of field */
- if (rcol(rp) < rreclen(rp)) {
- len = col - rcol(rp) + 1;
- }
-
- return (len);
- }
-
- /****************************************************************************/
- static int /* return error state (0=no error) */
- _rskipfld( /* skip to the next field */
- REC *rp, /* record pointer */
- size_t len) /* length of field if known, 0 if unknown */
- /****************************************************************************/
- {
- int err=0; /* error state (0=no error; EOF=past end-of-record) */
-
- /* if length of field is unknown */
- if (!len) {
- /* determine length */
- len=_rfldlen(rp);
- }
-
- /* if not at end of record */
- if (rcol(rp) <= rreclen(rp)) {
- /* move to next field */
- rcol(rp) += max(len, 1);
-
- /* error if attempt to move past end of record */
- } else {
- err = EOF;
- }
-
- rfldno(rp)++;
- return (err);
- }
-
- /****************************************************************************/
- static char * /* return trimmed string */
- _sctrimbegs( /* trim beginning of string */
- char *str, /* string to trim */
- int ch) /* character to match */
- /****************************************************************************/
- {
- char *sp; /* string pointer */
-
- if (str && *str && ch) {
- sp = str;
-
- /* increment through string while match is true */
- /* match any white space if ch is space */
- while ((ch == ' ') ? (isspace(*sp)) : (*sp == ch)) sp++;
-
- if (sp != str) memmove(str, sp, strlen(sp)+1);
- }
- return str;
- }
-
- /****************************************************************************/
- static char * /* return trimmed string */
- _sctrimends( /* trim end of string */
- char *str, /* string to trim */
- int ch) /* character to match */
- /****************************************************************************/
- {
- char *sp; /* string pointer */
-
- if (str && *str && ch) {
- /* point sp at last character in string */
- sp = str + strlen(str) - 1;
-
- /* decrement through string while match is true */
- /* match any white space if ch is space */
- while ((ch == ' ') ? (isspace(*sp)) : (*sp == ch)) {
- *sp = '\0';
- if (sp-- == str) break;
- }
- }
- return str;
- }
-
- /****************************************************************************/
- static char * /* return trimmed string */
- _sctrims( /* trim character from both ends of string */
- char *str, /* string to trim */
- int ch) /* character to match */
- /****************************************************************************/
- {
- return _sctrimbegs(_sctrimends(str, ch), ch);
- }
-
- /****************************************************************************/
- static char * /* return pointer to string */
- _rtrims( /* trim fldch, white space, and txtch */
- REC *rp, /* record pointer */
- char *str) /* string pointer */
- /****************************************************************************/
- {
- _sctrims(str, rfldch(rp));
- _sctrims(str, ' ');
- _sctrims(str, rtxtch(rp));
- return (str);
- }
-
- /****************************************************************************/
- char * /* return pointer to field buffer (NULL=error) */
- _rfldstr( /* copy field from record to field buffer */
- REC *rp, /* record pointer */
- size_t len) /* length of field if known; 0 if unknown */
- /****************************************************************************/
- {
- char *fldp=NULL; /* pointer to field buffer (NULL=error) */
- size_t fldlen=len; /* computed length of field */
-
- /* make sure first record is read from file */
- if (!rrecno(rp) && !rgetrec(rp)) goto done;
-
- /* if character delimited field, compute length */
- if (!fldlen) {
- fldlen=_rfldlen(rp);
-
- /* if column delimited field, avoid overflow */
- } else if (rcol(rp) > rreclen(rp)) {
- fldlen = 0;
- }
-
- /* ensure field buffer has sufficient memory */
- if (_rsetfldsiz(rp, fldlen)) goto done;
-
- /* copy field from record buffer to field buffer */
- /* note: a missing field results in an empty string */
- strncpy(rflds(rp), rrecs(rp)+rcol(rp), fldlen);
- rflds(rp)[fldlen] = '\0';
-
- /* set up for next field */
- _rskipfld(rp, max(fldlen, 1));
-
- /* if character delimited field, trim field buffer */
- if (!len) _rtrims(rp, rflds(rp));
-
- /* assign return pointer to field buffer */
- fldp = rflds(rp);
-
- done:
- return (fldp);
- }
-
- /****************************************************************************/
- char * /* return ptr to rec buffer (NULL=err or eof) */
- rgetrec( /* read next line from file into record buffer */
- REC *rp) /* record pointer */
- /****************************************************************************/
- {
- char *retp=NULL; /* return pointer (NULL=error or eof) */
- char str[FLDBUFSIZE+1]; /* temporary string */
-
-
- if (!_rstatus(rp, READ)) {
-
- /* initially allocate memory for record buffer */
- if (!rrecs(rp)) {
- if (_rsetrecsiz(rp, RECBUFSIZE)) goto done;
- }
-
- /* for each new record */
- rfldno(rp) = 0;
- rcol(rp) = 0;
- rrecno(rp)++;
- rreclen(rp) = 0;
- *rrecs(rp) = '\0';
-
- /* if at end of file, skip reading from file */
- if (reof(rp)) goto done;
-
- /* get next line from file into record buffer */
- if (!fgets(rrecs(rp), rrecsiz(rp), rfp(rp))) {
- /* set end-of-file indicator if no more records */
- rflags(rp) |= _R_EOF;
- goto done;
- }
- rreclen(rp) = strlen(rrecs(rp));
-
- /* if line longer than record buffer, extend record buffer */
- while (rrecs(rp)[rreclen(rp)-1] != '\n') {
- if (!fgets(str, FLDBUFSIZE+1, rfp(rp))) break;
- if (_rsetrecsiz(rp, rrecsiz(rp) + FLDBUFSIZE)) goto done;
- strncat(rrecs(rp), str, FLDBUFSIZE);
- rreclen(rp) = strlen(rrecs(rp));
- }
-
- /* trim end of record */
- _sctrimends(rrecs(rp), '\n');
-
- /* point retp to record buffer */
- retp = rrecs(rp);
- }
- done:
- return (retp);
- }
-
- /****************************************************************************/
- int /* return error number (0=no error) */
- rsetrecsiz( /* set record buffer size */
- REC *rp, /* record pointer */
- size_t recsiz) /* record buffer size */
- /****************************************************************************/
- {
- int errnum; /* error number (0=no error) */
-
- if (risvalid(rp)) {
- errnum = _rsetrecsiz(rp, recsiz);
- } else {
- errnum = rseterr(NULL, EINVAL);
- }
- return (errnum);
- }
-
- /****************************************************************************/
- int /* return error number (0=no error) */
- rsetfldsiz( /* set field buffer size */
- REC *rp, /* record pointer */
- size_t fldsiz) /* field buffer size */
- /****************************************************************************/
- {
- int errnum; /* error number (0=no error) */
-
- if (risvalid(rp)) {
- errnum = _rsetfldsiz(rp, fldsiz);
- } else {
- errnum = rseterr(NULL, EINVAL);
- }
- return (errnum);
- }
-
- /****************************************************************************/
- int /* return error number (0=no error) */
- rsetfldstr( /* copy string into field buffer; clear errors */
- REC *rp, /* record pointer */
- char *s) /* pointer to string */
- /****************************************************************************/
- {
- int errnum=0; /* error number (0=no error) */
- size_t fldsiz; /* required field buffer size */
-
- if (risvalid(rp)) {
- if (s) {
-
- /* ensure field buffer is large enough for string */
- fldsiz = strlen(s);
- if (fldsiz > rfldsiz(rp)) {
- errnum = _rsetfldsiz(rp, fldsiz);
- if (errnum) goto done;
- }
-
- /* copy string to field buffer */
- strcpy(rflds(rp), s);
-
- /* clear away any errors */
- rclearerr(rp);
-
- } else {
- errnum = rseterr(rp, R_EINVAL);
- }
- } else {
- errnum = rseterr(NULL, EINVAL);
- }
-
- done:
- return (errnum);
- }
-
- /****************************************************************************/
- int /* return number fields skipped; EOF on error */
- rskipnfld( /* skip over next number of fields */
- REC *rp, /* record pointer */
- size_t num) /* number of fields to skip over */
- /****************************************************************************/
- {
- int count=EOF; /* actual number of fields skipped (EOF=error) */
-
- if (!_rstatus(rp, READ)) {
-
- /* count number of fields to skip */
- count = 0;
- while (count < num) {
- /* but don't count past end of record */
- if (_rskipfld(rp, 0)) {
- break;
- }
- count++;
- }
- }
- return (count);
- }
-